package service

import (
	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/global"
	"awesomeProject/util"
	"context"
	"github.com/shopspring/decimal"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"strings"
	"time"
)

type ItemsIndicateSrv struct{}

func (i *ItemsIndicateSrv) Pagination(req request.ItemsIndicatePagination, shopIds []uint, operator model.User) response.Resp {
	offset := (req.PageIndex - 1) * req.PageSize
	filter := bson.D{}
	if req.ShopId != 0 {
		filter = append(filter, bson.E{Key: "shop_id", Value: req.ShopId})
	} else {
		if req.CompanyId != 0 && operator.SuperAdmin {
			var accounts []model.Account
			err := global.Gorm.Where("company_id=? and status=1", req.CompanyId).Find(&accounts).Error
			if err != nil {
				return response.ErrQuery
			}
			shopIds = []uint{}
			for _, account := range accounts {
				shopIds = append(shopIds, account.ShopId)
			}
		}
		if len(shopIds) > 0 {
			filter = append(filter, bson.E{Key: "shop_id", Value: bson.M{"$in": shopIds}})
		}
	}
	if req.SkuTypeValue != "" {
		if req.SkuType == "itemName" {
			filter = append(filter, bson.E{Key: "itemName", Value: bson.M{"$regex": "req.SkuTypeValue"}})
		} else if req.SkuType == "itemId" {
			filter = append(filter, bson.E{Key: "itemId", Value: util.GetInterfaceToInt(req.SkuTypeValue)})
		} else if req.SkuType == "itemNo" {
			filter = append(filter, bson.E{Key: "itemNo", Value: req.SkuTypeValue})
		}
	}
	if req.DateVal != "" {
		if req.DateType == 1 || req.DateType == 4 { // 日期
			filterDate, _ := time.Parse("2006-01-02", req.DateVal)

			filter = append(filter, bson.E{Key: "date", Value: filterDate.Format("20060102")})
		} else if req.DateType == 2 || req.DateType == 3 { // 近7天or近30天
			dateRange := strings.Split(req.DateVal, "~")
			sDate, _ := time.Parse("2006-01-02", dateRange[0])
			eDate, _ := time.Parse("2006-01-02", dateRange[1])
			filter = append(filter, bson.E{Key: "date", Value: bson.M{
				"$gte": sDate.Format("20060102"),
				"$lte": eDate.Format("20060102"),
			}})
		} else if req.DateType == 5 { // 月份
			month, _ := time.Parse("2006-01", req.DateVal)
			sd := util.GetMonthStartAndEnd(month.Year(), int(month.Month()))
			filter = append(filter, bson.E{Key: "date", Value: bson.M{
				"$gte": sd["start"].Format("20060102"),
				"$lte": sd["end"].Format("20060102"),
			}})
		}
	}
	match := bson.D{{
		"$match", filter,
	}}
	group := bson.D{{
		"$group", bson.D{
			{"_id", bson.D{
				{"shop_id", bson.M{"$toInt": "$shop_id"}},
				{"item_id", bson.M{"$toInt": "$item_id"}}},
			},
			{"item_name", bson.M{"$last": "$item_name"}},
			{"item_no", bson.M{"$last": "$item_no"}},
			{"image", bson.M{"$last": "$image"}},
			{"ctm_item_click_cnt", bson.M{"$sum": bson.M{"$toInt": "$ctm_item_click_cnt"}}},
			{"ctm_item_click_uv", bson.M{"$sum": bson.M{"$toInt": "$ctm_item_click_uv"}}},
			{"ctm_item_view_cnt", bson.M{"$sum": bson.M{"$toInt": "$ctm_item_view_cnt"}}},
			{"ctm_item_view_uv", bson.M{"$sum": bson.M{"$toInt": "$ctm_item_view_uv"}}},
			{"item_cart_cnt", bson.M{"$sum": bson.M{"$toInt": "$item_cart_cnt"}}},
			{"item_cart_uv", bson.M{"$sum": bson.M{"$toInt": "$item_cart_uv"}}},
			{"item_order_cnt", bson.M{"$sum": bson.M{"$toInt": "$item_order_cnt"}}},
			{"item_purchase_cnt", bson.M{"$sum": bson.M{"$toInt": "$item_purchase_cnt"}}},
			{"item_purchase_uv", bson.M{"$sum": bson.M{"$toInt": "$item_purchase_uv"}}},
			{"item_verified_cnt", bson.M{"$sum": bson.M{"$toInt": "$item_verified_cnt"}}},
			{"item_verified_usd", bson.M{"$sum": bson.M{"$toDouble": "$item_verified_usd"}}},
			{"item_verified_uv", bson.M{"$sum": bson.M{"$toInt": "$item_verified_uv"}}},
			{"item_view_pv", bson.M{"$sum": bson.M{"$toInt": "$item_view_pv"}}},
			{"order_uv", bson.M{"$sum": bson.M{"$toInt": "$order_uv"}}},
			{"purchase_usd", bson.M{"$sum": bson.M{"$toInt": "$purchase_usd"}}},
			{"item_view_uv", bson.M{"$sum": bson.M{"$toInt": "$item_view_uv"}}},
			{"item_wishlist_cnt", bson.M{"$sum": bson.M{"$toInt": "$item_wishlist_cnt"}}},
		},
	}}
	sort := bson.D{{"$sort", bson.M{"ctm_item_view_cnt": -1}}}
	skip := bson.D{{"$skip", offset}}
	limit := bson.D{{"$limit", req.PageSize}}
	count := bson.D{{"$count", "total"}}
	countCursor, err := global.MongoDB.Collection("items_indicate").Aggregate(
		context.TODO(),
		mongo.Pipeline{match, group, count},
	)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var countResult []map[string]interface{}
	if err = countCursor.All(context.TODO(), &countResult); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	cursor, err := global.MongoDB.Collection("items_indicate").Aggregate(
		context.TODO(),
		mongo.Pipeline{match, group, sort, skip, limit},
	)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var itemsIndicates []model.ItemsIndicate
	if err = cursor.All(context.TODO(), &itemsIndicates); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if len(itemsIndicates) == 0 {
		return response.OK.WithData(map[string]interface{}{
			"total": 0,
			"list":  itemsIndicates,
		})
	}
	// 计算逻辑
	for key, val := range itemsIndicates {
		// 曝光点击率=商品详情页浏览量/商品曝光量
		val.CtmItemViewRateNew =
			util.Div(
				decimal.NewFromInt(int64(val.CtmItemClickCnt)),
				decimal.NewFromInt(int64(val.CtmItemViewCnt)),
			)
		// 加购率=加购人数/访客数
		val.CtmCartViewRate =
			util.Div(
				decimal.NewFromInt(int64(val.ItemCartUv)),
				decimal.NewFromInt(int64(val.CtmItemClickUv)),
			)
		// 下单转化率=商品下单人数/访客数
		val.CtmOrderViewRate =
			util.Div(
				decimal.NewFromInt(int64(val.ItemViewUv)),
				decimal.NewFromInt(int64(val.CtmItemClickUv)),
			)
		itemsIndicates[key] = val
	}

	var itemsIndicatesExtra []model.ItemsIndicateWithExtra
	if len(itemsIndicates) > 0 {
		for _, itemsIndicate := range itemsIndicates {
			itemsIndicateExtra := model.ItemsIndicateWithExtra{}
			util.StructAssign(&itemsIndicateExtra, &itemsIndicate)
			shopId := itemsIndicate.ID["shop_id"]
			itemId := itemsIndicate.ID["item_id"]
			where := bson.D{
				{"shopId", shopId},
				{"itemId", itemId},
			}
			var overmerchant model.OrderMerchantList
			err2 := global.MongoDB.Collection("merchant_list").FindOne(context.TODO(), where).Decode(&overmerchant)
			if err2 == nil {
				itemsIndicateExtra.PreCreatedAtString = overmerchant.PreCreatedAtString
			}
			itemsIndicatesExtra = append(itemsIndicatesExtra, itemsIndicateExtra)
		}
	}

	return response.OK.WithData(map[string]interface{}{
		"total": countResult[0]["total"],
		//"list":  itemsIndicates,
		"list":  itemsIndicatesExtra,
	})
}
